#region Using References

using System;
using System.Diagnostics.Contracts;
using Beaker.OpenCube.Mapping;
using Beaker.OpenCube.Nbt;

#endregion

namespace Beaker.OpenCube.Game
{
	/// <summary>
	/// 
	/// </summary>
	public sealed class Item
		: ObservableExpandoObject
	{
		private sbyte _slotIndex;

		/// <summary>
		/// Gets or sets the index of the slot the item is in.
		/// </summary>
		/// <value>
		/// The index of the slot the item is in.
		/// </value>
		[Mapping( Name = "Slot", IsOptional = true )]
		public sbyte SlotIndex
		{
			get
			{
				Contract.Ensures( Contract.Result<sbyte>() >= 0 );
				return _slotIndex;
			}
			set
			{
				Contract.Requires<ArgumentOutOfRangeException>( value >= 0 );
				SetValue( ref _slotIndex, value );
			}
		}

		private short _id;

		/// <summary>
		/// Gets or sets the Item or Block id.
		/// </summary>
		/// <value>
		/// The Item or Block id.
		/// </value>
		[Mapping( Name = "id" )]
		public short Id
		{
			get
			{
				Contract.Ensures( Contract.Result<short>() >= 0 );
				return _id;
			}
			set
			{
				Contract.Requires<ArgumentOutOfRangeException>( value >= 0 );
				SetValue( ref _id, value );
			}
		}

		private short _dataValue;

		/// <summary>
		/// Gets or sets the data value.
		/// </summary>
		/// <value>
		/// The data value.
		/// </value>
		/// <remarks>The name of this property in the actual NBT structure is 'Damage', 
		/// which comes from when only tools used this value, 
		/// now many other items use this value for other purposes.</remarks>
		[Mapping( Name = "Damage" )]
		public short DataValue
		{
			get
			{
				Contract.Ensures( Contract.Result<short>() >= 0 );
				return _dataValue;
			}
			set
			{
				Contract.Requires<ArgumentOutOfRangeException>( value >= 0 );
				SetValue( ref _dataValue, value );
			}
		}

		private ObservableExpandoObject _tag;

		/// <summary>
		/// Additional information about the item. Optional for most items.
		/// </summary>
		[Mapping( Tag = NbtTag.Compound, Name = "tag", IsOptional = true )]
		public ObservableExpandoObject Tag
		{
			get { return _tag; }
			set { SetValue( ref _tag, value ); }
		}
	}
}